#include "lit/elf/segList.h"
#include "lit/elf/elfFile.h"
#include "lit/elf/block.h"
#include "lit/report/report.h"
#include <memory>

void SegList::allocAddr(const std::string &segName, u32 &base, u32 &off) {
    // 设置对齐前的elf文件偏移
    begin = off;

    u32 align = DISC_ALIGN;
    if (segName == ".text") {
        align = TEXT_ALIGN;
    }
    // 对齐elf文件偏移
    off += (align - off % align) % align;
    // 更新当前段的段基址
    base += (MEM_ALIGN - base % MEM_ALIGN) % MEM_ALIGN + off % MEM_ALIGN;

    baseAddr = base;
    offset = off;
    size = 0;

    // 遍历所有elf文件中段名为segName的段
    for (u32 i = 0; i < ownerList.size(); ++i) {
        std::shared_ptr<Elf32_Shdr> seg = ownerList[i]->shdrTable[segName];
        u32 sh_align = seg->sh_addralign;
        size += (sh_align - size % sh_align) % sh_align;
        char buffer[seg->sh_size];
        ownerList[i]->getData(buffer, seg->sh_offset, seg->sh_size);
        blocks.emplace_back(std::make_shared<Block>((char *) (buffer), size, seg->sh_size));
        seg->sh_addr = base + size;
        size += seg->sh_size;
    }
    base += size;
    off += size;
}


void SegList::relocAddr(u32 relAddr, u8 type, u32 symAddr) {
    u32 relOffset = relAddr - baseAddr;   //同类合并段的数据偏移
    // 查找修正地址所在位置
    std::shared_ptr<Block> b;
    for (int i = 0; i < blocks.size(); ++i) {
        if (blocks[i]->offset <= relOffset && blocks[i]->offset + blocks[i]->size > relOffset) {
            b = blocks[i];
            break;
        }
    }
    // 地址修正
    int *pAddr = (int *) (b->data + relOffset - b->offset);
    todo("重定位功能尚未实现!");
}